/*
 * Tools.java
 *
 * Created on 2007/1/3 10:24
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package org.sais.eswn.tool;

import java.util.logging.Level;
import java.util.logging.Logger;

import java.awt.*;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import java.util.ArrayList;
import javax.sound.sampled.*;
import javax.swing.*;
import javax.swing.text.*;

import org.sais.eswn.card.Card;
import org.sais.eswn.card.CardText.CardTextBuilder;

/**
 *
 * @author Romulus
 * @last edited by Julius on 2008/12/14
 */
public class Tools {

    private static HashMap<String, Card> cdata = new HashMap<String, Card>();
    private static ArrayList<String> loc = new ArrayList<String>();
    public static HashMap<Integer, String> pron = new HashMap<Integer, String>();
    public static boolean customizedIcon = false;
    // public static CardViewer cardviewer;
    public static Object sLock = new Object();


    static {
        try {
            readLocale();
            readCardBase();
        //readPronunciation();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    static public Card getCard(String cardno) {
        return cdata.get(cardno);
    }

    static public HashMap<String, Card> getCardDataBase() {
        return cdata;
    }

    static public String getLoc(int index) {
        return loc.get(index);
    }

    static public final byte[] itoba(int value) {
        return new byte[]{(byte) (value >>> 24), (byte) (value >> 16 & 0xff), (byte) (value >> 8 & 0xff), (byte) (value & 0xff)};
    }

    static public final int batoi(byte[] value) {
        return (value[0] & 0xff) * 0x1000000 + (value[1] & 0xff) * 0x10000 + (value[2] & 0xff) * 0x100 + (value[3] & 0xff);
    }

    public static void readLocale() throws FileNotFoundException, IOException {     //Read Locale File for Messages
        char[] buf = new char[1];
        String bs = "";
        InputStreamReader locale = null;

        /*        File file = new File("locale\\" + java.util.ResourceBundle.getBundle("Global").getString("locale.txt"));
        if (file.exists()) {
        locale = new InputStreamReader(new FileInputStream(file), "UTF-8");
        } else {*/
        locale = new ReadInnerFile("locale.txt").stream;
        /*}*/
        while (locale.read(buf, 0, 1) > 0) {
            bs += buf[0];
            if (buf[0] == '\n') {
                loc.add(bs.substring(0, bs.length() - 2));
                bs = "";
            }
        }
        locale.close();
    }

    public static void readCardBase() throws FileNotFoundException, IOException {      //Read Card Data Base
        InputStreamReader cardlistfile = new ReadInnerFile("carddatabases.txt").stream;
        execReadCardDataBase(cardlistfile);
    }

    public static Set<String> listCardNos() {
        return cdata.keySet();
    }

    private static void execReadCardDataBase(InputStreamReader cardlistfile) {
        char[] buf = new char[1];
        String pp = new String();  //Buffer String for parse
        int step = 0;
        String no = "";
        Card card = new Card();
        CardTextBuilder textb = new CardTextBuilder();

        try {
            while (cardlistfile.read(buf, 0, 1) > 0) {  //Read database
                switch (buf[0]) {  //parse txtfile into objects
                    case '\n':
                        pp = pp.substring(0, pp.length() - 1);  //deletee tail \r
                        switch (step) {
                            case 0:
                                no = pp.trim();
                                card = new Card();
                                card.no = no;
                                textb = new CardTextBuilder();
                                pp = "";
                                step++;
                                break;
                            case 1:
                                card.name = pp.trim();
                                pp = "";
                                if (no.charAt(0) == 'C' || no.charAt(0) == 'H') {
                                    step += 2;
                                } else {
                                    step++;
                                }
                                break;
                            case 2:
                                // Seperate character and others
                                textb.cost = Float.parseFloat(pp);
                                pp = "";
                                step++;
                                break;
                            case 3:
                                if (!pp.equals(null)) {
                                    textb.ruleText += pp + "\n";
                                }
                                pp = "";
                                break;
                        }
                        break;
                    case '#':
                        //cardlistfile.skip(5);  //"end\r\n"
                        while (cardlistfile.read(buf, 0, 1) > 0) {
                            if (buf[0] == '\n') {
                                break;
                            }
                        }
                        card.text = textb.build();
                        cdata.put(no, card);
                        step = 0;
                        pp = "";
                        textb = new CardTextBuilder();
                        break;
                    default:
                        pp = pp + buf[0];
                        break;
                }
            }
        } catch (Exception ex) {
            System.out.println("step=" + step + ", cnt=" + cdata.size() + ", lastcarnum=" + no);
            System.out.println("pp=" + pp);
            ex.printStackTrace();
        }
    }

    public static void readPronunciation() {
        try {
            pron.clear();
            BufferedReader in = new BufferedReader(new ReadInnerFile("pronunciation.txt").stream);
            String line = in.readLine();
            while (line != null) {
                String[] s = line.split("<>");
                if (s.length < 2) {
                    break;
                }
                pron.put(Tools.safeParseInt(s[0]), s[1]);
                line = in.readLine();
            }
            in.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static String getPronunciation(Integer cardnum) {
        return pron.get(cardnum) != null ? pron.get(cardnum) : "";
    }

    public static void showCard(String cardno, JTextPane SCArea) {
        try {
            SCArea.setText("");
            if (cardno == null) {
                SCArea.setBackground(Color.white);
                return;
            }
            Card card = cdata.get(cardno);
            SCArea.setBackground(card.getDisplayColor());
            SimpleAttributeSet set = new SimpleAttributeSet();
            SCArea.setCharacterAttributes(set, true);
            Document doc = SCArea.getStyledDocument();

            /*            String pronunciation = getPronunciation(scard.CardNumber);
            doc.insertString(doc.getLength(), pronunciation + "\n", set);*/

            StyleConstants.setFontSize(set, 16);
            StyleConstants.setBold(set, true);
            doc.insertString(doc.getLength(), card.name + "\n", set);
            StyleConstants.setFontSize(set, 12);
            StyleConstants.setBold(set, false);

            doc.insertString(doc.getLength(), "\n" + card.text.getDisplayText(), set);
            doc.insertString(doc.getLength(), "\nNo." + card.no, set);

            SCArea.setCaretPosition(0);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void updateConfig(String prefix, String content) {  //Remember to use all lower case string in prefix
        try {
            if (content == null) {
                return;
            }
            String line;
            BufferedReader fr = new BufferedReader(new InputStreamReader(new FileInputStream(new File("config.ini")), "UTF-8"));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("configtemp.ini")), "UTF-8"));
            boolean found = false;
            line = fr.readLine();
            while (line != null) {
                String lineprefix = "";
                if (line.contains("=")) {
                    lineprefix = line.substring(0, line.indexOf("=")).trim().toLowerCase();
                }
                if (lineprefix.equals(prefix)) {
                    bw.write(prefix + " = " + content + "\r\n");
                    found = true;
                } else {
                    if (line.endsWith("\n")) {
                        bw.write(line);
                    } else {
                        bw.write(line + "\r\n");
                    }
                }
                line = fr.readLine();
            }
            if (!found) {
                bw.write(prefix + " = " + content + "\r\n");
            }
            fr.close();
            bw.close();
            new File("config.ini").delete();
            new File("configtemp.ini").renameTo(new File("config.ini"));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static String readConfig(String prefix) {
        return readConfig(prefix, "");
    }

    /**
     * Read a config entry. Remember to use all lower case string in prefix.
     * @param prefix All lower-case entry name.
     * @return The config entry.
     */
    public static String readConfig(String prefix, String defaultValue) {
        try {
            String line;
            File configfile = new File("config.ini");
            if (!configfile.exists()) {
                new FileOutputStream(configfile).write(0);
            }
            BufferedReader fr = new BufferedReader(new InputStreamReader(new FileInputStream(configfile), "UTF-8"));
            line = fr.readLine();
            while (line != null) {
                if (line.contains("=")) {
                    String lineprefix = line.substring(0, line.indexOf("=")).trim().toLowerCase();
                    if (lineprefix.equals(prefix)) {
                        fr.close();
                        String sub = line.substring(prefix.length());
                        return sub.substring(sub.indexOf("=") + 1).trim();
                    }
                }
                line = fr.readLine();
            }
            fr.close();
            return defaultValue;
        } catch (Exception ex) {
            ex.printStackTrace();
            return defaultValue;
        }
    }

    public static void playSound(String filename) {
        try {
            InputStream in = new ReadInnerFile(filename).u.openStream();
            AudioInputStream stream = AudioSystem.getAudioInputStream(in);
            AudioFormat format = stream.getFormat();
            DataLine.Info info = new DataLine.Info(Clip.class, format);
            final Clip clip = (Clip) AudioSystem.getLine(info);
            clip.open(stream);

            clip.addLineListener(new LineListener() {

                @Override
                public void update(LineEvent event) {
                    if (event.getType() == LineEvent.Type.STOP) {
                        clip.stop();
                    }
                }
            });

            clip.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static String getNowTimeString(String format) {
        SimpleDateFormat D = new SimpleDateFormat(format);
        Date Now = new Date();
        long Time = Now.getTime();
        Time = Time + 100000L;
        return D.format(new Date(Time));
    }

    public static boolean XOR(boolean a, boolean b) {
        if ((a && b) || (!a && !b)) {
            return false;
        } else {
            return true;
        }
    }

    public static int safeParseInt(String s) {
        s = s.replace(" ", "");
        if (s.length() == 0) {
            return 0;
        }
        try {
            return Integer.parseInt(s);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return -1;
        }
    }
    static long[] timer = new long[2];
    static int nowtimer = 0;


    static {
        timer[0] = 0;
        timer[1] = 0;
    }

    static void startTimer() {
        timer[nowtimer] = new Date().getTime();
    }

    static void switchTimer() {
        long interval = new Date().getTime() - timer[nowtimer];
        System.out.println("Interval is " + interval + " miliseconds.");
        nowtimer = nowtimer == 0 ? 1 : 0;
        timer[nowtimer] = new Date().getTime();
    }
    static long intervaltimer;

    public static long interval() {
        long now = new Date().getTime();
        long ret = now - intervaltimer;
        intervaltimer = now;
        return ret;
    }

    public static String parseLocale(int index, String[] arg) {
        String ret = loc.get(index);
        int i = 1;
        for (String s : arg) {
            ret = ret.replace("%" + i, s);
            ++i;
        }
        return ret;
    }

    /**
     * @author Julius
     * @param sceneName
     * @param BGMPath
     *
     */
    public static void loadSceneList(ArrayList<String> sceneName) {


        try {
            String line;

            BufferedReader fr = new BufferedReader(new ReadInnerFile("SceneList.txt").stream);
            line = fr.readLine();
            while (line != null) {
                sceneName.add(line);
                line = fr.readLine();
                line = fr.readLine();
            }
            fr.close();

        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }

    public static void loadBGM(ArrayList<String> sceneName, ArrayList<String> BGMPath) {


        loadSceneList(sceneName);
        for (int i = 0; i < sceneName.size(); i++) {
            BGMPath.add("");
        }
        try {
            String line;
            File configfile = new File("SceneBGM.txt");
            if (!configfile.exists()) {
                configfile.createNewFile();
            }
            BufferedReader fr = new BufferedReader(new InputStreamReader(new FileInputStream(configfile), "UTF-8"));
            int counter = 0;
            line = fr.readLine();
            while (line != null) {

                line = fr.readLine();
                if (line != null) {
                    BGMPath.set(counter, line);
                    counter++;
                }
                line = fr.readLine();
            }
            fr.close();

        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }

    public static void updateBGM(ArrayList<String> sceneName, ArrayList<String> BGMPath) {


        try {
            String line;
            File configfile = new File("SceneBGM.txt");
            if (!configfile.exists()) {
                new FileOutputStream(configfile).write(0);
            }
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configfile), "UTF-8"));
            for (int i = 0; i < sceneName.size(); i++) {
                fw.write(sceneName.get(i));
                fw.newLine();
                if (BGMPath.get(i) != null) {
                    fw.write(BGMPath.get(i));
                } else {
                    fw.write("");
                }

                fw.newLine();
            }
            fw.close();

        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }

    public static void loadBG(ArrayList<String> BGName, ArrayList<String> BGPath) {

        loadSceneList(BGName);
        for (int i = 0; i < BGName.size(); i++) {
            BGPath.add("");
        }
        try {
            String line;
            File configfile = new File("background.txt");
            if (!configfile.exists()) {
                configfile.createNewFile();
            }
            BufferedReader fr = new BufferedReader(new InputStreamReader(new FileInputStream(configfile), "UTF-8"));
            int counter = 0;
            line = fr.readLine();
            while (line != null) {

                line = fr.readLine();
                if (line != null) {
                    BGPath.set(counter, line);
                    counter++;
                }

                line = fr.readLine();
            }
            fr.close();

        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }

    public static void updateBG(ArrayList<String> BGName, ArrayList<String> BGPath) {


        try {
            String line;
            File configfile = new File("background.txt");
            if (!configfile.exists()) {
                new FileOutputStream(configfile).write(0);
            }
            BufferedWriter fw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configfile), "UTF-8"));
            for (int i = 0; i < BGName.size(); i++) {
                fw.write(BGName.get(i));
                fw.newLine();
                if (BGPath.get(i) != null) {
                    fw.write(BGPath.get(i));
                } else {
                    fw.write("");
                }

                fw.newLine();
            }
            fw.close();

        } catch (Exception ex) {
            ex.printStackTrace();

        }
    }

    public static void setMyFont(Component Comp, Font myFont) {
        //  Font myFont = new Font(java.util.ResourceBundle.getBundle("fantasyfestafront/Bundle").getString("FrontFrame.default.font"), Font.PLAIN, 12);
        if (Comp != null) {
            try {
                Comp.setFont(myFont);
            } catch (Exception e) {
                return;
            }
        }
        if (Comp instanceof Container) {
            Component[] components = ((Container) Comp).getComponents();
            for (int i = 0; i < components.length; i++) {
                Component child = components[i];
                if (child != null) {
                    //System.out.println(child.getClass().getName());
                    setMyFont(child, myFont);
                }
            }
        }
        return;
    }

    public static void setLocale() {

        String language = Tools.readConfig("language");
        String country = Tools.readConfig("country");

        if (!language.equals("")) {
            Locale locale;
            if (!country.equals("")) {
                locale = new Locale(language, country);
            } else {
                locale = new Locale(language);
            }
            Locale.setDefault(locale);
            System.out.println(language + country + locale);
        } else {
            Locale.setDefault(Locale.JAPAN);
        }


    }

    public static boolean isURLAvailable(String url) {
        boolean result = false;
        int count = 0;
        int state = -1;

        try {

            if (url == null || url.length() < 0) {
                result = false;
            }
            while (count < 5) {
                URL urlStr = new URL(url);
                HttpURLConnection connection = (HttpURLConnection) urlStr.openConnection();
                state = connection.getResponseCode();
                if (state == 200) {
                    result = true;
                    break;
                } else {
                    count++;
                }
            }

        } catch (MalformedURLException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        }

        return result;
    }

    public static void setMyOpaque(JComponent con) {
        for (Component comp : con.getComponents()) {
            if (comp instanceof JComponent) {
                if (comp instanceof JScrollPane) {
                    ((JScrollPane) comp).getViewport().setOpaque(false);
                    ((JScrollPane) comp).getHorizontalScrollBar().setOpaque(false);
                    ((JScrollPane) comp).getVerticalScrollBar().setOpaque(false);
                }
                if (!(comp instanceof JTextComponent)) {
                    ((JComponent) comp).setOpaque(false);

                }
                //  ((JComponent)comp).setOpaque(false);
                setMyOpaque((JComponent) comp);
            }
        }
    }

    public static void exportCardList(ArrayList<String> nos) {
        try {
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("exported_carddatabase.txt"), "UTF-8"), 8192);
            for (String no : nos) {
                Card c = getCard(no);
                out.write(no + "\r\n");
                out.write(c.name + "\r\n");
                // out.write(c.text.getExportText(c.getType()));
                out.write("\r\n");
            }
            out.close();
            JOptionPane.showMessageDialog(null, "Card list exported.");
        } catch (IOException ex) {
            Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

interface CardGameDisplayInterface {

    abstract void ShowTextinJTextPane();
}